import type { WebSocketMessage } from '../types';

export type WebSocketEventHandler = (data: any) => void;

export class WebSocketClient {
  private ws: WebSocket | null = null;
  private url: string;
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 10;
  private reconnectInterval = 2000;
  private isConnecting = false;
  private isManuallyDisconnected = false;
  private heartbeatTimer?: number;
  private heartbeatInterval = 30000; // 30秒心跳
  private eventHandlers: Map<string, Set<WebSocketEventHandler>> = new Map();

  constructor(url: string = 'ws://localhost:12290/ws') {
    this.url = url;
  }

  // 连接WebSocket
  connect(): Promise<void> {
    if (this.isConnecting || (this.ws && this.ws.readyState === WebSocket.CONNECTING)) {
      return Promise.resolve();
    }

    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      return Promise.resolve();
    }

    this.isConnecting = true;

    return new Promise((resolve, reject) => {
      try {
        this.ws = new WebSocket(this.url);

        this.ws.onopen = () => {
          console.log('WebSocket 连接已建立');
          this.isConnecting = false;
          this.reconnectAttempts = 0;
          this.isManuallyDisconnected = false;
          
          // 订阅所有事件类型
          this.subscribe('transaction');
          this.subscribe('rule_matched');
          this.subscribe('proxy_status');
          this.subscribe('error');
          
          // 启动心跳
          this.startHeartbeat();
          
          // 触发连接状态变化事件
          this.triggerConnectionEvent('connected');
          
          resolve();
        };

        this.ws.onmessage = (event) => {
          try {
            const message: WebSocketMessage = JSON.parse(event.data);
            this.handleMessage(message);
          } catch (error) {
            console.error('解析WebSocket消息失败:', error);
          }
        };

        this.ws.onclose = (event) => {
          console.log('WebSocket 连接已关闭:', event.code, event.reason);
          this.isConnecting = false;
          this.ws = null;
          
          // 停止心跳
          this.stopHeartbeat();
          
          // 触发连接状态变化事件
          this.triggerConnectionEvent('disconnected');

          // 如果不是手动关闭，尝试重连
          if (!this.isManuallyDisconnected && event.code !== 1000 && this.reconnectAttempts < this.maxReconnectAttempts) {
            this.scheduleReconnect();
          } else if (this.reconnectAttempts >= this.maxReconnectAttempts) {
            console.error('达到最大重连次数，停止重连');
            this.triggerConnectionEvent('failed');
          }
        };

        this.ws.onerror = (error) => {
          console.error('WebSocket 错误:', error);
          this.isConnecting = false;
          reject(error);
        };

      } catch (error) {
        this.isConnecting = false;
        reject(error);
      }
    });
  }

  // 断开连接
  disconnect(): void {
    this.isManuallyDisconnected = true;
    this.stopHeartbeat();
    if (this.ws) {
      this.ws.close(1000, '手动断开连接');
      this.ws = null;
    }
  }

  // 发送消息
  send(message: any): void {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify(message));
    } else {
      console.warn('WebSocket 未连接，无法发送消息');
    }
  }

  // 订阅事件类型
  subscribe(eventType: string): void {
    this.send({
      type: 'subscribe',
      data: { eventType }
    });
  }

  // 取消订阅事件类型
  unsubscribe(eventType: string): void {
    this.send({
      type: 'unsubscribe',
      data: { eventType }
    });
  }

  // 发送心跳
  ping(): void {
    this.send({
      type: 'ping',
      data: { timestamp: Date.now() }
    });
  }

  // 添加事件监听器
  on(eventType: string, handler: WebSocketEventHandler): void {
    if (!this.eventHandlers.has(eventType)) {
      this.eventHandlers.set(eventType, new Set());
    }
    this.eventHandlers.get(eventType)!.add(handler);
  }

  // 移除事件监听器
  off(eventType: string, handler: WebSocketEventHandler): void {
    const handlers = this.eventHandlers.get(eventType);
    if (handlers) {
      handlers.delete(handler);
      if (handlers.size === 0) {
        this.eventHandlers.delete(eventType);
      }
    }
  }

  // 移除所有事件监听器
  removeAllListeners(eventType?: string): void {
    if (eventType) {
      this.eventHandlers.delete(eventType);
    } else {
      this.eventHandlers.clear();
    }
  }

  // 处理接收到的消息
  private handleMessage(message: WebSocketMessage): void {
    const { type, data, timestamp } = message;
    
    // 触发对应类型的事件处理器
    const handlers = this.eventHandlers.get(type);
    if (handlers) {
      handlers.forEach(handler => {
        try {
          handler(data);
        } catch (error) {
          console.error(`处理 ${type} 事件时发生错误:`, error);
        }
      });
    }

    // 触发通用事件处理器
    const allHandlers = this.eventHandlers.get('*');
    if (allHandlers) {
      allHandlers.forEach(handler => {
        try {
          handler({ type, data, timestamp });
        } catch (error) {
          console.error('处理通用事件时发生错误:', error);
        }
      });
    }

    // 处理特殊消息类型
    switch (type) {
      case 'connection':
        console.log('WebSocket 连接确认:', data);
        break;
      case 'pong':
        console.log('收到心跳响应:', data);
        break;
      case 'error':
        console.error('服务器错误:', data);
        break;
    }
  }

  // 安排重连
  private scheduleReconnect(): void {
    this.reconnectAttempts++;
    console.log(`准备重连 WebSocket (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);
    
    // 触发重连状态事件
    this.triggerConnectionEvent('reconnecting');
    
    setTimeout(() => {
      this.connect().catch(error => {
        console.error('重连失败:', error);
        if (this.reconnectAttempts < this.maxReconnectAttempts) {
          this.scheduleReconnect();
        } else {
          console.error('达到最大重连次数，停止重连');
          this.triggerConnectionEvent('failed');
        }
      });
    }, this.reconnectInterval * Math.min(this.reconnectAttempts, 5)); // 指数退避
  }

  // 获取连接状态
  get readyState(): number {
    return this.ws ? this.ws.readyState : WebSocket.CLOSED;
  }

  // 是否已连接
  get isConnected(): boolean {
    return this.ws ? this.ws.readyState === WebSocket.OPEN : false;
  }

  // 启动心跳
  private startHeartbeat(): void {
    this.stopHeartbeat();
    this.heartbeatTimer = window.setInterval(() => {
      if (this.isConnected) {
        this.ping();
      }
    }, this.heartbeatInterval);
  }

  // 停止心跳
  private stopHeartbeat(): void {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = undefined;
    }
  }

  // 触发连接状态变化事件
  private triggerConnectionEvent(status: 'connected' | 'disconnected' | 'reconnecting' | 'failed'): void {
    const handlers = this.eventHandlers.get('connection_status');
    if (handlers) {
      handlers.forEach(handler => {
        try {
          handler({ status, attempts: this.reconnectAttempts });
        } catch (error) {
          console.error('处理连接状态事件时发生错误:', error);
        }
      });
    }
  }

  // 强制重连
  public forceReconnect(): void {
    console.log('强制重连WebSocket...');
    this.isManuallyDisconnected = false;
    this.reconnectAttempts = 0;
    this.disconnect();
    setTimeout(() => {
      this.connect().catch(error => {
        console.error('强制重连失败:', error);
      });
    }, 1000);
  }
}

// 创建单例实例
export const wsClient = new WebSocketClient();
export default wsClient; 